package com.astrob.model;

import java.io.EOFException;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.util.ArrayList;

import android.graphics.Bitmap;
import android.graphics.BitmapFactory;

public class JuncViewBmpHandle {
	public class MyRandomAccessFile extends RandomAccessFile {
		public MyRandomAccessFile(File file, String mode)
				throws FileNotFoundException {
			super(file, mode);
		}

		public int readMyInt() {
			byte[] buffer = new byte[4];
			try {
				if (read(buffer, 0, buffer.length) != buffer.length) {
					throw new EOFException();
				}
			} catch (EOFException e) {
				e.printStackTrace();
			} catch (IOException e) {
				e.printStackTrace();
			}
			return ((buffer[3] & 0xff) << 24) + ((buffer[2] & 0xff) << 16)
					+ ((buffer[1] & 0xff) << 8) + (buffer[0] & 0xff);
		}
	}

	MyRandomAccessFile mFileReader = null;

	public class FileReaderHeader {
		int nUncompLenth;
		int nPos;
		int nSize;
		String strFileName;
	}

	private ArrayList<FileReaderHeader> m_objHeaderList = new ArrayList<FileReaderHeader>();
	private FileReaderHeader m_curHeader = null;

	public JuncViewBmpHandle() {
	}

	public boolean OpenFile(String szFilePath) {
		if (null == szFilePath)
			return false;
		File file = new File(szFilePath);
		if (null == file || file.exists() == false)
			return false;
		try {
			mFileReader = new MyRandomAccessFile(file, "r");
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}
		ReadHeaderData();
		if (null == mFileReader)
			return false;
		return true;
	}

	public Bitmap GetBitmap(String szFileName) {
		int size = GetFileSize(szFileName);
		if (size <= 0)
			return null;
		byte[] buffer = new byte[size];
		if (!ReadFile(buffer))
			return null;
		Bitmap bitmap = BitmapFactory.decodeByteArray(buffer, 0, size);
		return bitmap;
	}

	public int GetFileSize(String szFileName) {
		int index = FindFile(szFileName);
		if (index < 0)
			return 0;
		m_curHeader = m_objHeaderList.get(index);
		int size = m_curHeader.nUncompLenth;
		if (size <= 0)
			size = m_curHeader.nSize;
		return size;
	}

	public boolean ReadFile(byte[] buffer) {
		if (m_curHeader == null || mFileReader == null)
			return false;
		try {
			mFileReader.seek(m_curHeader.nPos);
			mFileReader.read(buffer);
		} catch (IOException e) {
			e.printStackTrace();
		}
		return true;
	}

	public void Close() {
		if (m_objHeaderList != null)
			m_objHeaderList.clear();
		try {
			if (mFileReader != null)
				mFileReader.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private int FindFile(String szFileName) {
		int size = m_objHeaderList.size();
		if (size <= 0)
			return -1;
		String name = szFileName.toUpperCase();
		int index = QuichSearch(0, size, name);
		return index;
	}

	private int QuichSearch(int nIndexL, int nIndexR, String name) {
		if (nIndexL > nIndexR) {
			return -1;
		}
		int nIndexTemp = 0;
		while (true) {
			nIndexTemp = (nIndexL + nIndexR) >> 1;
			FileReaderHeader header = m_objHeaderList.get(nIndexTemp);

			int nResult = name.compareTo(header.strFileName);
			if (nResult == 0) {
				return nIndexTemp;
			} else {
				if (nIndexTemp == nIndexL || nIndexTemp == nIndexR)// 当找不到时，会在两个相邻的元素陷入死循环
				{
					return -1;
				}

				if (nResult > 0)// 大于
				{
					nIndexL = nIndexTemp;
				} else// 小于
				{
					nIndexR = nIndexTemp;
				}
			}
			if (nIndexR == nIndexL) {
				return -1;
			}
		}
	}

	private void ReadHeaderData() {
		try {
			byte[] szCorp = new byte[8];
			byte[] szVer = new byte[8];
			mFileReader.read(szCorp);
			mFileReader.read(szVer);
			@SuppressWarnings("unused")
			int nCA = mFileReader.readMyInt();
			@SuppressWarnings("unused")
			int nFileSize = mFileReader.readMyInt();
			int nCount = mFileReader.readMyInt();
			int nDataOffset = mFileReader.readMyInt();
			int lLastPos = (int) mFileReader.getFilePointer();
			int headlen = nDataOffset - lLastPos;
			byte[] buf = new byte[headlen];
			mFileReader.read(buf);
			int structsize = 20;
			for (int i = 0; i < nCount; ++i) {
				int bufpos = i * structsize;
				int nFileNamePos = ((buf[bufpos + 3] & 0xff) << 24)
						+ ((buf[bufpos + 2] & 0xff) << 16)
						+ ((buf[bufpos + 1] & 0xff) << 8)
						+ (buf[bufpos] & 0xff);
				byte cNameLenth = buf[i * structsize + 4];
				@SuppressWarnings("unused")
				byte cFileType = buf[i * structsize + 4 + 1];
				// pass two null byte
				bufpos = i * structsize + 8;
				int nUncompLenth = ((buf[bufpos + 3] & 0xff) << 24)
						+ ((buf[bufpos + 2] & 0xff) << 16)
						+ ((buf[bufpos + 1] & 0xff) << 8)
						+ (buf[bufpos] & 0xff);
				bufpos = i * structsize + 12;
				int nPos = ((buf[bufpos + 3] & 0xff) << 24)
						+ ((buf[bufpos + 2] & 0xff) << 16)
						+ ((buf[bufpos + 1] & 0xff) << 8)
						+ (buf[bufpos] & 0xff);
				bufpos = i * structsize + 16;
				int nSize = ((buf[bufpos + 3] & 0xff) << 24)
						+ ((buf[bufpos + 2] & 0xff) << 16)
						+ ((buf[bufpos + 1] & 0xff) << 8)
						+ (buf[bufpos] & 0xff);

				FileReaderHeader header = new FileReaderHeader();
				byte[] szFileName = new byte[cNameLenth];
				System.arraycopy(buf, nFileNamePos - lLastPos, szFileName, 0,
						cNameLenth);
				header.strFileName = new String(szFileName, "UTF-8");
				header.nUncompLenth = nUncompLenth;
				header.nPos = nPos;
				header.nSize = nSize;
				m_objHeaderList.add(header);
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
}
